#region License
// Copyright (c) 2007 James Newton-King
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion

using System;
using System.Collections.Generic;
using System.Net.Mail;
using NUnit.Framework;
using Utilities.Email;
using Utilities.Miscellaneous;
using Utilities.Testing;
using Rhino.Mocks;
using Utilities.IO;

namespace Utilities.Test.Email
{
  public class EmailControllerFixture : TestFixtureBase
  {
    [Test]
    public void Simple()
    {
      IEmailSender mockEmailSender = Repository.CreateMock<IEmailSender>();
      using (Repository.Record())
      {
        mockEmailSender.SendMail(null);
        LastCall.On(mockEmailSender).Callback(new Func<MailMessage, bool>(
          delegate(MailMessage message)
          {
            Assert.AreEqual("james.newtonking@newtonsoft.com", message.From.Address);
            Assert.AreEqual(1, message.To.Count);
            Assert.AreEqual("test@test.com", message.To[0].Address);
            Assert.AreEqual("Test subject", message.Subject);
            Assert.AreEqual("Test body.", message.Body);
            Assert.AreEqual(0, message.CC.Count);
            Assert.AreEqual(0, message.Bcc.Count);
            Assert.AreEqual(0, message.Attachments.Count);
            Assert.AreEqual(MailPriority.Normal, message.Priority);
            Assert.AreEqual(false, message.IsBodyHtml);

            return true;
          }));
      }
      using (Repository.Playback())
      {
        EmailController emailController = new EmailController(null, new MailAddress("james.newtonking@newtonsoft.com"), null, null, true);
        emailController.EmailSender = mockEmailSender;

        emailController.SendEmail(null, EmailUtils.ParseEmailAddresses("test@test.com"), "Test subject", "Test body.", false, new List<Attachment>());
      }
    }

    [Test]
    public void Template()
    {
      IEmailSender mockEmailSender = Repository.CreateMock<IEmailSender>();
      using (Repository.Record())
      {
        mockEmailSender.SendMail(null);
        LastCall.On(mockEmailSender).Callback(new Func<MailMessage, bool>(
          delegate(MailMessage message)
          {
            Assert.AreEqual("james.newtonking@newtonsoft.com", message.From.Address);
            Assert.AreEqual(1, message.To.Count);
            Assert.AreEqual("test@test.com", message.To[0].Address);
            Assert.AreEqual("Test subject - This is test param string", message.Subject);
            Assert.AreEqual(@"<html>
  <body>
    <p>
          TestParamString: This is test param string<br />
          TestParamInteger: 42</p>
  </body>
</html>", message.Body);
            Assert.AreEqual(0, message.CC.Count);
            Assert.AreEqual(0, message.Bcc.Count);
            Assert.AreEqual(0, message.Attachments.Count);
            Assert.AreEqual(MailPriority.Normal, message.Priority);
            Assert.AreEqual(true, message.IsBodyHtml);

            return true;
          }));
      }
      using (Repository.Playback())
      {
        EmailController emailController = new EmailController(null, new MailAddress("james.newtonking@newtonsoft.com"), null, null, true);
        emailController.EmailSender = mockEmailSender;

        string templatePath = FileUtils.MapPath("~/Email/TestTemplate.xslt");

        IDictionary<string, object> parameters = new Dictionary<string, object>();
        parameters.Add("TestParamString", "This is test param string");
        parameters.Add("TestParamInteger", 42);

        emailController.SendEmail(EmailUtils.ParseEmailAddresses("test@test.com"), templatePath, parameters, new List<Attachment>());
      }
    }

    [Test]
    public void OverrideEmailAddress()
    {
      IEmailSender mockEmailSender = Repository.CreateMock<IEmailSender>();

      using (Repository.Record())
      {
        mockEmailSender.SendMail(null);
        LastCall.On(mockEmailSender).Callback(new Func<MailMessage, bool>(
          delegate(MailMessage message)
          {
            Assert.AreEqual("james.newtonking@newtonsoft.com", message.From.Address);
            Assert.AreEqual(1, message.To.Count);
            Assert.AreEqual("override@test.com", message.To[0].Address);
            Assert.AreEqual("Test subject (Message intended for: test@test.com)", message.Subject);
            Assert.AreEqual("Test body.", message.Body);
            Assert.AreEqual(0, message.CC.Count);
            Assert.AreEqual(0, message.Bcc.Count);
            Assert.AreEqual(0, message.Attachments.Count);
            Assert.AreEqual(MailPriority.Normal, message.Priority);
            Assert.AreEqual(true, message.IsBodyHtml);

            return true;
          }));
      }
      using (Repository.Playback())
      {
        EmailController emailController = new EmailController(EmailUtils.ParseEmailAddresses("override@test.com"), new MailAddress("james.newtonking@newtonsoft.com"), null, null, true);
        emailController.EmailSender = mockEmailSender;

        emailController.SendEmail(null, EmailUtils.ParseEmailAddresses("test@test.com"), "Test subject", "Test body.", true, new List<Attachment>());
      }
    }

    [Test]
    [ExpectedException(typeof(ArgumentNullException), ExpectedMessage = @"No fromEmailAddress specified and no default from email address was given to the EmailController.
Parameter name: fromEmailAddress")]
    public void EmailControllerNullFromAddressNoDefaultDefined()
    {
      EmailController emailController = new EmailController(null, null, null, null, true);
      emailController.EmailSender = Repository.CreateMock<IEmailSender>();

      emailController.SendEmail(null, EmailUtils.ParseEmailAddresses("test@test.com"), "Test subject", "Test body.", true, new List<Attachment>());
    }

    [Test]
    [ExpectedException(typeof(ArgumentNullException), ExpectedMessage = @"Value cannot be null.
Parameter name: toEmailAddresses")]
    public void EmailControllerNullToAddresses()
    {
      EmailController emailController = new EmailController(null, null, null, null, true);
      emailController.EmailSender = Repository.CreateMock<IEmailSender>();

      emailController.SendEmail(new MailAddress("james.newtonking@newtonsoft.com"), null, "Test subject", "Test body.", true, new List<Attachment>());
    }

    [Test]
    [ExpectedException(typeof(ArgumentException), ExpectedMessage = @"No to email address(es) provided.
Parameter name: toEmailAddresses")]
    public void EmailControllerEmptyToAddresses()
    {
      EmailController emailController = new EmailController(null, null, null, null, true);
      emailController.EmailSender = Repository.CreateMock<IEmailSender>();

      emailController.SendEmail(new MailAddress("james.newtonking@newtonsoft.com"), new MailAddressCollection(), "Test subject", "Test body.", true, new List<Attachment>());
    }

    [Test]
    [ExpectedException(typeof(InvalidOperationException), ExpectedMessage = @"No email sender set on controller.")]
    public void EmailControllerNoEmailSender()
    {
      EmailController emailController = new EmailController(null, null, null, null, true);

      emailController.SendEmail(new MailAddress("james.newtonking@newtonsoft.com"), EmailUtils.ParseEmailAddresses("test@test.com"), "Test subject", "Test body.", true, new List<Attachment>());
    }
  }
}